package cn.zyjblogs.config.security;

import cn.zyjblogs.config.handler.ResourceAccessDeniedHandler;
import cn.zyjblogs.config.handler.ResourceAuthenticationEntryPoint;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;

import java.util.List;

/**
 * @author zhuyijun
 */
@Configuration
@EnableResourceServer
@RequiredArgsConstructor
@EnableConfigurationProperties(WhiteListProperties.class)
@RefreshScope
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Value("${spring.application.name}")
    private String resourceId;
    private final TokenStore tokenStore;
    private final WhiteListProperties whiteListProperties;
//    private final CsrfTokenRepository oauthCsrfTokenRepository;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId(resourceId)
                // 验证令牌的服务
                .tokenStore(tokenStore)
                .stateless(true)
                .accessDeniedHandler(new ResourceAccessDeniedHandler())
                .authenticationEntryPoint(new ResourceAuthenticationEntryPoint());
    }

    /**
     * 资源服务器拦截优先级高于Spring Scurity，限制资源服务器作用范围
     *
     * @param http
     * @return void
     * @author zhuyijun
     * @date 2022/9/18 下午10:52
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        List<String> allowPaths = whiteListProperties.getAllowPaths();
        String[] strings = allowPaths.toArray(new String[0]);
        http.csrf().disable()
//                .disable()
                //限制资源服务器作用范围为 "/user/**", "/demo/**"
                .requestMatchers().antMatchers("/v*/**", "/demo/**").antMatchers(strings)
                .and()
                .formLogin()
                .and()
                .authorizeRequests()
                .antMatchers(strings).permitAll()
                .antMatchers("/v*/user/login", "/v*/auth/refresh/token", "/v*/auth/authorize/code")
                .permitAll()
                .antMatchers("/v*/**").access("#oauth2.hasAnyScope('oauth','all')")
                //以下请求必须认证通过
                .anyRequest()
                .authenticated().and()

                .httpBasic();
    }

}
